package com.bcx.wind.workflow.imp.cmd.managercmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.TaskLevel;
import com.bcx.wind.workflow.core.constant.TaskStatus;
import com.bcx.wind.workflow.core.constant.WorkflowOperate;
import com.bcx.wind.workflow.entity.WindActHistory;
import com.bcx.wind.workflow.entity.WindTask;
import com.bcx.wind.workflow.entity.WindTaskActor;
import com.bcx.wind.workflow.interceptor.Command;
import com.bcx.wind.workflow.interceptor.CommandContext;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.JsonHelper;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.List;

import static com.bcx.wind.workflow.message.ErrorCode.MAIN_TASK_IS_NULL;
import static com.bcx.wind.workflow.message.ErrorCode.NO_AUTH_ON_CHILD_TASK;
import static com.bcx.wind.workflow.message.ErrorCode.TASK_NOT_SUPPORT_OPERATE;

/**
 * 完成子任务
 *
 * @author zhanglei
 */
public class CompleteChildTaskCommand implements Command<Integer> {

    /**
     * 子任务ID
     */
    private String taskId;

    /**
     * 任务操作人
     */
    private WindUser user;

    /**
     * 建议
     */
    private String suggest;

    private CommandContext context;

    public CompleteChildTaskCommand(String taskId,WindUser user,String suggest){
        this.taskId = taskId;
        this.user = user;
        this.suggest = suggest;
    }

    @Override
    public Integer executor(CommandContext context) {
        try{
            this.context = context;
            return execute();
        }catch (Exception e){
            return 0;
        }
    }


    private Integer execute() {
        checkArgs();

        //删除子任务以及操作人
        context.access().removeTaskInstanceById(this.taskId);
        context.access().removeTaskActorByTaskId(taskId);

        //更新历史履历
        changeHistory();
        return 1;
    }


    private  void changeHistory(){
        QueryFilter filter = new QueryFilter()
                .setTaskId(this.taskId);
        List<WindActHistory> actHistories = this.context.access().selectActiveHistoryList(filter);

        if(!ObjectHelper.isEmpty(actHistories)){
            WindActHistory actHistory =  actHistories.get(0);
            actHistory.setActorId(user().proxyUserId())
                    .setActorName(user().proxyUserName())
                    .setApproveTime(TimeHelper.nowDate())
                    .setSuggest(this.suggest)
                    .setSubmitUserVariable(JsonHelper.toJson(this.user()))
                    .setOperate(WorkflowOperate.complete.name());
            this.context.access().updateActiveHistory(actHistory);
        }
    }



    private void checkArgs(){
        //校验任务
        Assert.notEmptyError(MAIN_TASK_IS_NULL,this.taskId);
        QueryFilter filter = new QueryFilter()
                .setTaskId(this.taskId)
                .setTaskLevel(TaskLevel.main.name());
        List<WindTask> windTasks = context.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(MAIN_TASK_IS_NULL,windTasks);
        WindTask task = windTasks.get(0);
        Assert.isTrueError(TASK_NOT_SUPPORT_OPERATE,!TaskStatus.run.name().equals(task.getStatus()));

        //校验审批人
        QueryFilter actorFilter = new QueryFilter()
                .setTaskId(this.taskId);
        List<WindTaskActor> actors = context.access().selectTaskActorList(actorFilter);
        Assert.notEmptyError(NO_AUTH_ON_CHILD_TASK,actors);
        Assert.isTrueError(NO_AUTH_ON_CHILD_TASK,ObjectHelper.isEmpty(this.user) || ObjectHelper.isEmpty(this.user.getUserId()));

        boolean exist = false;
        for(WindTaskActor actor : actors){
            if(actor.getActorId().equals(this.user.proxyUserId())){
                exist = true;
                break;
            }
        }
        Assert.isTrueError(NO_AUTH_ON_CHILD_TASK,!exist);
    }



    private WindUser user(){
        return this.user == null ? new WindUser()
                .setUserId("admin")
                .setUserName("管理员") : this.user;
    }
}
